import sys, traceback, pdb
from construct2 import *


#===============================================================================
# testing machinary
#===============================================================================
def debug():
    t, v, tb = sys.exc_info()
    traceback.print_exception(t, v, tb)
    print >>sys.stderr, "*********"
    pdb.post_mortem(tb)

def test(c, data, expected = None):
    success = True
    print "testing", c.name
    
    if expected is None:
        expected = data
    
    print "\tparsing: ",
    try:
        o = c.parse(data)
    except:
        success = False
        print "FAILURE\n"
        debug()
        return
    else:
        print "OKAY"
    
    print "\tbuilding:",
    try:
        raw = c.build(o)
        assert raw == expected
    except:
        success = False
        print "FAILURE\n"
        debug()
    else:
        print "OKAY"
    
    return success


#===============================================================================
# tests
#===============================================================================
test(UBInt8("UBInt8"), "\x01")
test(ULInt8("ULInt8"), "\x01")
test(UNInt8("UNInt8"), "\x01")
test(SBInt8("SBInt8"), "\x01")
test(SLInt8("SLInt8"), "\x01")
test(SNInt8("SNInt8"), "\x01")

test(UBInt16("UBInt16"), "\x00\x01")
test(ULInt16("ULInt16"), "\x00\x01")
test(UNInt16("UNInt16"), "\x00\x01")
test(SBInt16("SBInt16"), "\x00\x01")
test(SLInt16("SLInt16"), "\x00\x01")
test(SNInt16("SNInt16"), "\x00\x01")

test(UBInt32("UBInt32"), "\x00\x00\x00\x01")
test(ULInt32("ULInt32"), "\x00\x00\x00\x01")
test(UNInt32("UNInt32"), "\x00\x00\x00\x01")
test(SBInt32("SBInt32"), "\x00\x00\x00\x01")
test(SLInt32("SLInt32"), "\x00\x00\x00\x01")
test(SNInt32("SNInt32"), "\x00\x00\x00\x01")

test(UBInt64("UBInt64"), "\x00\x00\x00\x00\x00\x00\x00\x01")
test(ULInt64("ULInt64"), "\x00\x00\x00\x00\x00\x00\x00\x01")
test(UNInt64("UNInt64"), "\x00\x00\x00\x00\x00\x00\x00\x01")
test(SBInt64("SBInt64"), "\x00\x00\x00\x00\x00\x00\x00\x01")
test(SLInt64("SLInt64"), "\x00\x00\x00\x00\x00\x00\x00\x01")
test(SNInt64("SNInt64"), "\x00\x00\x00\x00\x00\x00\x00\x01")

test(BFloat32("BFloat32"), "\x01\x02\x03\x04")
test(LFloat32("LFloat32"), "\x01\x02\x03\x04")
test(NFloat32("NFloat32"), "\x01\x02\x03\x04")

test(BFloat64("BFloat64"), "\x01\x02\x03\x04\x05\x06\x07\x08")
test(LFloat64("LFloat64"), "\x01\x02\x03\x04\x05\x06\x07\x08")
test(NFloat64("NFloat64"), "\x01\x02\x03\x04\x05\x06\x07\x08")

test(GreedyRepeater(UBInt16("GreedyRepeater")), "AABB")
test(GreedyRepeater(UBInt16("GreedyRepeater")), "AABBC", "AABB")
test(OptionalGreedyRepeater(UBInt16("OptionalGreedyRepeater1")), "AAAA")
test(OptionalGreedyRepeater(UBInt16("OptionalGreedyRepeater2")), "A", "")
test(StrictRepeater(2, UBInt16("StrictRepeater")), "AABB")
test(Optional(UBInt16("Optional1")), "AAAA", "AA")
test(Optional(UBInt16("Optional2")), "A", "")

test(OneOfValidator(UBInt8("OneOfValidator"), [1, 2, 3]), "\x02")
test(NoneOfValidator(UBInt8("NoneOfValidator"), [1, 2, 3]), "\x05")

test(String("String1", 3), "ABC")
test(String("String2", 5, paddir = "left"), "ABC\x00\x00")
test(String("String3", 5, paddir = "right"), "\x00\x00ABC")
test(CString("CString"), "hello\x00")
test(PascalString("PascalString1"), "\x05hello")
test(PascalString("PascalString2", lengthfield = ULInt16), "\x05\x00hello")


#===============================================================================
# todo
#===============================================================================
# struct
# bitstruct
# union
# bitfield 
# padding 
# bit
# nibble
# flag
# enum
# flag
# flags enum
# embed
# embedded bit string
# if then else
# length value
# expr adapter
# anchor
# rename
# value
# pass
# terminate
# if
# switch
# meta repeater
# meta field
# repeat until
# 










